package com.yu.admin.modules.system.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yu.admin.common.util.session.AdminSessionUtil;
import com.yu.admin.modules.system.mapper.LoginLogMapper;
import com.yu.admin.modules.system.mapper.SysUserMapper;
import com.yu.admin.modules.system.mapper.UserRoleMapper;
import com.yu.admin.modules.system.pojo.LoginLog;
import com.yu.admin.modules.system.pojo.SysUser;
import com.yu.admin.modules.system.pojo.UserRole;
import com.yu.admin.modules.system.pojo.dto.SysUserDTO;
import com.yu.admin.modules.system.pojo.vo.SysUserLoginVO;
import com.yu.admin.modules.system.pojo.vo.UpdatePasswordVo;
import com.yu.admin.modules.system.service.SysUserService;
import com.yu.common.constant.Const;
import com.yu.common.exception.ServiceException;
import com.yu.common.service.RedisService;
import com.yu.common.util.GeneratorUtil;
import com.yu.common.util.browser.UserAgentUtils;
import com.yu.common.util.ip.IpUtil;
import com.yu.common.util.jwt.JWTUtil;
import cz.mallat.uasparser.UserAgentInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class SysUserServiceImpl implements SysUserService {

    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private RedisService redisService;
    @Resource
    private UserRoleMapper sysUserRoleMapper;
    @Resource
    private LoginLogMapper loginLogMapper;

    @Transactional
    public SysUserDTO login(SysUserLoginVO loginVo, HttpServletRequest request) throws Exception {
        // 校对验证码
        String verifyCode = (String) redisService.get(Const.CONST_verify_code_redis_prefix + loginVo.getUuid());
        redisService.del(Const.CONST_verify_code_redis_prefix + loginVo.getUuid());
        if (StringUtils.isEmpty(verifyCode) || !verifyCode.equals(loginVo.getVerifyCode()))
            throw ServiceException.CONST_verify_code_error_or_expire;

        SysUser user = sysUserMapper.selectOne(new QueryWrapper<SysUser>()
                .eq("username", loginVo.getUsername())
                .eq("password", GeneratorUtil.md5Base64(loginVo.getPassword())));
        // 登录日志
        System.out.println(request.getRemoteHost());
        LoginLog loginLog = new LoginLog();
        loginLog.setUsername(loginVo.getUsername());
        loginLog.setIp(IpUtil.getIp(request));
        loginLog.setTimestamp(new Date());
        UserAgentInfo userAgentInfo = UserAgentUtils.parse(request.getHeader("User-Agent"));
        if (userAgentInfo != null) {
            loginLog.setOsName(userAgentInfo.getOsFamily());
            loginLog.setBrowserName(userAgentInfo.getUaFamily());
        }
        if (user == null) {
            loginLogMapper.insert(loginLog);
            log.error("[管理员登录失败] {}", loginLog);
            throw ServiceException.CONST_login_failed;
        }

        if (!user.getStatus()) {
            loginLogMapper.insert(loginLog);
            log.error("[管理员登录失败 账号冻结] {}", loginLog);
            throw ServiceException.CONST_user_is_forbidden;
        }

        SysUserDTO userDTO = new SysUserDTO();
        BeanUtils.copyProperties(user, userDTO, "password");
        // 获取权限
        userDTO.setPermissions(sysUserRoleMapper.selectPermissionsOfUser(user.getId()));
        AdminSessionUtil.setSysUserSession(userDTO);

        loginLog.setSuccess(true);
        loginLogMapper.insert(loginLog);
        log.info("[管理员登录] {}", loginLog);
        return userDTO;
    }

    public boolean checkLogin(String token) throws ServiceException {
        return redisService.hasKey(Const.CONST_sys_user_session_redis_prefix + JWTUtil.getSysUserId(token));
    }

    public void logout(String token) throws ServiceException {
        redisService.del(Const.CONST_sys_user_session_redis_prefix + JWTUtil.getSysUserId(token));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void setRoleOfSysUser(Integer userId, List<Integer> roleIds) {
        sysUserRoleMapper.delete(new QueryWrapper<UserRole>().eq("user_id", userId)); // 先删除之前的角色
        UserRole userRole = new UserRole();
        userRole.setUserId(userId);
        for (Integer roleId : roleIds) {
            userRole.setRoleId(roleId);
            sysUserRoleMapper.insert(userRole);
        }
    }

    @Transactional
    @Override
    public int updatePassword(Integer userId, UpdatePasswordVo params) throws ServiceException {
        if (StringUtils.isEmpty(params.getOldPassword()) || StringUtils.isEmpty(params.getNewPassword())
                || params.getNewPassword().length() < 6 || params.getNewPassword().length() > 18)
            throw ServiceException.CONST_password_pattern_error;
        if (params.getOldPassword().equals(params.getNewPassword()))
            throw ServiceException.CONST_new_password_can_not_equals_old_password;

        SysUser user = sysUserMapper.selectById(AdminSessionUtil.getCurrentSysUserId());
        if (!GeneratorUtil.md5Base64(params.getOldPassword()).equals(user.getPassword()))
            throw ServiceException.CONST_old_password_error;

        user.setPassword(GeneratorUtil.md5Base64(params.getNewPassword()));
        return sysUserMapper.updateById(user);
    }


}
